//
// Created by wubh2 on 2023/2/27.
//

#include "bsp_uart.h"
#include "task_communicate.h"
#include "task_lostcounter.h"
#include "driver_remote.h"
/**
  * @brief Text strings printed on PC Com port for user information
  */
//uint8_t aTextInfoStart[] = "\r\nUSART Example : Enter characters to fill reception buffers.\r\n";

uint8_t aRXBufferUser[RX_BUFFER_SIZE];

/**
  * @brief Data buffers used to manage received data in interrupt routine
  */
uint8_t aRXBufferA[RX_BUFFER_SIZE];
uint8_t aRXBufferB[RX_BUFFER_SIZE];

__IO uint32_t uwNbReceivedChars;
uint8_t* pBufferReadyForUser;
uint8_t* pBufferReadyForReception;
QueueHandle_t rxQueue = NULL;
QueueHandle_t txQueue = NULL;

/**
  * @brief  Send Txt information message on UART Tx line (to PC Com port).
  * @param  huart UART handle.
  * @param  String String to be sent to user display
  * @param  Size   Size of string
  * @retval None
  */
void PrintInfo(UART_HandleTypeDef* huart, uint8_t* String, uint16_t Size)
{
    if (HAL_OK != HAL_UART_Transmit(huart, String, Size, 100))
    {
        Error_Handler();
    }
}

/**
  * @brief  This function prints user info on PC com port and initiates RX transfer
  * @retval None
  */
void StartReception(void)
{
    /* Initializes Buffer swap mechanism (used in User callback) :
       - 2 physical buffers aRXBufferA and aRXBufferB (RX_BUFFER_SIZE length)
    */
    pBufferReadyForReception = aRXBufferA;
    pBufferReadyForUser = aRXBufferB;
    uwNbReceivedChars = 0;

    if (rxQueue == NULL)
        rxQueue = xQueueCreate(256, 1);
    if (txQueue == NULL)
        txQueue = xQueueCreate(256, 1);

    /* Print user info on PC com port */
    //PrintInfo(&USE_UART, aTextInfoStart, COUNTOF(aTextInfoStart));

    /* Initializes Rx sequence using Reception To Idle event API.
       As DMA channel associated to UART Rx is configured as Circular,
       reception is endless.
       If reception has to be stopped, call to HAL_UART_AbortReceive() could be used.

       Use of HAL_UARTEx_ReceiveToIdle_DMA service, will generate calls to
       user defined HAL_UARTEx_RxEventCallback callback for each occurrence of
       following events :
       - DMA RX Half Transfer event (HT)
       - DMA RX Transfer Complete event (TC)
       - IDLE event on UART Rx line (indicating a pause is UART reception flow)
    */
    HAL_UARTEx_ReceiveToIdle_DMA(&USE_UART, aRXBufferUser, RX_BUFFER_SIZE);

}

/**
  * @brief  This function handles buffer containing received data on PC com port
  * @note   In this example, received data are sent back on UART Tx (loopback)
  *         Any other processing such as copying received data in a larger buffer to make it
  *         available for application, could be implemented here.
  * @note   This routine is executed in Interrupt context.
  * @param  huart UART handle.
  * @param  pData Pointer on received data buffer to be processed
  * @retval Size  Nb of received characters available in buffer
  */
void UserDataTreatment(UART_HandleTypeDef* huart, uint8_t* pData, uint16_t Size)
{
    /*
     * This function might be called in any of the following interrupt contexts :
     *  - DMA TC and HT events
     *  - UART IDLE line event
     *
     * pData and Size defines the buffer where received data have been copied, in order to be processed.
     * During this processing of already received data, reception is still ongoing.
     *
     */
    uint8_t* pBuff = pData;
    uint8_t i;

    /* Implementation of loopback is on purpose implemented in direct register access,
       in order to be able to echo received characters as fast as they are received.
       Wait for TC flag to be raised at end of transmit is then removed, only TXE is checked */
    for (i = 0; i < Size; i++)
    {
        while (!(__HAL_UART_GET_FLAG(huart, UART_FLAG_TXE)))
        {

        }
        huart->Instance->DR = *pBuff;
        pBuff++;
    }

}

void Judge_Recv(UART_HandleTypeDef* huart, uint16_t Size)
{
    static uint8_t old_pos = 0;
    uint8_t* ptemp;
    uint8_t i;

    /* Check if number of received data in recpetion buffer has changed */
    if (Size != old_pos)
    {
        /* Check if position of index in reception buffer has simply be increased
           of if end of buffer has been reached */
        if (Size > old_pos)
        {
            /* Current position is higher than previous one */
            uwNbReceivedChars = Size - old_pos;
            /* Copy received data in "User" buffer for evacuation */
            for (i = 0; i < uwNbReceivedChars; i++)
            {
                pBufferReadyForUser[i] = aRXBufferUser[old_pos + i];
                xQueueSendFromISR(rxQueue, &pBufferReadyForUser[i], 0);
            }
        }
        else
        {
            /* Current position is lower than previous one : end of buffer has been reached */
            /* First copy data from current position till end of buffer */
            uwNbReceivedChars = RX_BUFFER_SIZE - old_pos;
            /* Copy received data in "User" buffer for evacuation */
            for (i = 0; i < uwNbReceivedChars; i++)
            {
                pBufferReadyForUser[i] = aRXBufferUser[old_pos + i];
                xQueueSendFromISR(rxQueue, &pBufferReadyForUser[i],0);
            }
            /* Check and continue with beginning of buffer */
            if (Size > 0)
            {
                for (i = 0; i < Size; i++)
                {
                    //TODO:这里改了，记得得看看是否有影响
                    pBufferReadyForUser[uwNbReceivedChars + i] = aRXBufferUser[i];
                    xQueueSendFromISR(rxQueue, &pBufferReadyForUser[uwNbReceivedChars + i], 0);
                }
                uwNbReceivedChars += Size;
            }
        }
        /* Process received data that has been extracted from Rx User buffer */
        UserDataTreatment(huart, pBufferReadyForUser, uwNbReceivedChars);

        /* Swap buffers for next bytes to be processed */
        ptemp = pBufferReadyForUser;
        pBufferReadyForUser = pBufferReadyForReception;
        pBufferReadyForReception = ptemp;
    }
    /* Update old_pos as new reference of position in User Rx buffer that
       indicates position to which data have been processed */
    old_pos = Size;
}

/**
  * @brief  User implementation of the Reception Event Callback
  *         (Rx event notification called after use of advanced reception service).
  * @param  huart UART handle
  * @param  Size  Number of data available in application reception buffer (indicates a position in
  *               reception buffer until which, data are available)
  * @retval None
  */
extern Remote_message_t remote_message;
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size)
{

    if (huart->Instance == huart6.Instance) {
        Judge_Recv(huart, Size);
    }


}

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */

//void Error_Handler(void)
//{
//	/* USER CODE BEGIN Error_Handler_Debug */
//	/* User can add his own implementation to report the HAL error return state */
//	while (1)
//	{
//		/* Toggle LED2 for error */
//		//BSP_LED_Toggle(LED2);
//		HAL_Delay(500);
//	}
//	/* USER CODE END Error_Handler_Debug */
//}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
	 tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

void usart_dma_send(usart_param_struct *usart_param, const uint8_t *pData, uint32_t _size)
{
    if (usart_param->tx_finish_flag) {
        HAL_UART_Transmit_DMA(usart_param->huart, pData, _size);
        __HAL_DMA_DISABLE_IT(usart_param->huart->hdmatx, DMA_IT_HT);
        usart_param->tx_finish_flag = 0;
    }
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    /* Prevent unused argument(s) compilation warning */
    if(huart == judgement_usart.huart)
        judgement_usart.tx_finish_flag = 1;
    /* NOTE: This function should not be modified, when the callback is needed,
             the HAL_UART_TxCpltCallback could be implemented in the user file
     */
}